package hydrap2p.manager;

import java.util.LinkedList;
import java.util.List;

public class Tree<T> {
	private T payload;
	private List<Tree<T>> parents;
	private List<Tree<T>> children;
	
	public Tree(T payload)
	{
		parents=new LinkedList<Tree<T>>();
		children=new LinkedList<Tree<T>>();
		this.payload=payload;
	}

	public boolean isParent(Tree<T> child)
	{
		synchronized(children)
		{
			return children.contains(child);
		}
	}
	public boolean isChild(Tree<T> parent)
	{
		synchronized(parents)
		{
			return parents.contains(parent);
		}
	}
	public int countParents()
	{
		synchronized(parents)
		{
			return parents.size();
		}
	}
	public int countChildren()
	{
		synchronized(children)
		{
			return children.size();
		}
	}
	
	public void addChild(Tree<T> child)
	{
		synchronized(children)
		{
			if (!children.contains(child))
				 children.add(child);
			if (!parents.contains(this))
				child.parents.add(this);
		}
	}
	public void addChild(T payload)
	{
		addChild(new Tree<T>(payload));
	}
	public void removeChild(Tree<T> child)
	{
		synchronized(children)
		{
			children.remove(child);
			child.parents.remove(this);
		}
	}
	public List<Tree<T>> getParents()
	{
		synchronized(parents)
		{
			List<Tree<T>> ret=new LinkedList<Tree<T>>();
			for (Tree<T> parent : parents)
				ret.add(parent);
			return ret;
		}
	}
	/**
	 * Returns a read-only view of the children
	 * @return
	 */
	public List<Tree<T>> getChildren()
	{
		synchronized(children)
		{
			List<Tree<T>> ret=new LinkedList<Tree<T>>();
			for (Tree<T> child : children)
				ret.add(child);
			return ret;
		}
	}
	public Tree<T> getChildByPayload(T payload)
	{
		for (Tree<T> child : children)
			if (child.payload.equals(payload))
				return child;
		return null;
	}
	public Tree<T> getChildByPayloadRecursive(T payload)
	{
		for (Tree<T> child : children)
		{
			if (child.payload.equals(payload))
				return child;
			
			Tree<T> ret=child.getChildByPayloadRecursive(payload);
			if (ret!=null)
				return ret;
		}
		return null;
	}
	public T getPayload()
	{
		return payload;
	}
	
	@Override
	public boolean equals(Object o)
	{
		if (! (o instanceof Tree<?>))
			return false;
		Tree<?> temp = (Tree<?>)o;
		return payload.equals(temp.getPayload());
	}
	@Override
	public int hashCode()
	{
		return payload.hashCode();
	}
}
